/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package dcc;

import java.awt.TrayIcon.MessageType;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;

import javax.swing.Icon;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import dcc.shannonfano.Decoder;
import dcc.shannonfano.Encoder;

/**
 * 
 * @author Atuan
 */
public class MainWindow extends javax.swing.JPanel implements DocumentListener {

	private CompressionAlgorithm compressionAlgorithm;
	private JFileChooser loadFileChooser;
	private JFileChooser selectFolderChooser;

	private static String inputFilePath = "";

	/**
	 * Creates new form MainWindow
	 */
	public MainWindow() {
		initComponents();
		loadFileChooser = new JFileChooser();
		selectFolderChooser = new JFileChooser();

		outputTextField.getDocument().addDocumentListener(this);
		rleButton.setActionCommand("rle");
		shannonfanoButton.setActionCommand("sf");
		lzwButton.setActionCommand("lzw");
	}

	/**
	 * This method is called from within the constructor to initialize the form.
	 * WARNING: Do NOT modify this code. The content of this method is always
	 * regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")
	// <editor-fold defaultstate="collapsed"
	// desc="Generated Code">//GEN-BEGIN:initComponents
	private void initComponents() {

		buttonGroup1 = new javax.swing.ButtonGroup();
		loadFileButton = new javax.swing.JButton();
		inputLabel = new javax.swing.JLabel();
		outputTextField = new javax.swing.JTextField();
		selectFolderButton = new javax.swing.JButton();
		compressButton = new javax.swing.JButton();
		decompressButton = new javax.swing.JButton();
		rleButton = new javax.swing.JRadioButton();
		shannonfanoButton = new javax.swing.JRadioButton();
		lzwButton = new javax.swing.JRadioButton();
		jLabel1 = new javax.swing.JLabel();
		messageLabel = new javax.swing.JLabel();

		loadFileButton.setText("Load File");
		loadFileButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				loadFileButtonActionPerformed(evt);
			}
		});

		outputTextField.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				outputTextFieldActionPerformed(evt);
			}
		});

		selectFolderButton.setText("Select folder");
		selectFolderButton
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						selectFolderButtonActionPerformed(evt);
					}
				});

		compressButton.setText("Compress");
		compressButton.setEnabled(false);
		compressButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				compressButtonActionPerformed(evt);
			}
		});

		decompressButton.setText("Decompress");
		decompressButton.setEnabled(false);
		decompressButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				decompressButtonActionPerformed(evt);
			}
		});

		buttonGroup1.add(rleButton);
		rleButton.setText("Run-length encoding");
		rleButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				rleButtonActionPerformed(evt);
			}
		});

		buttonGroup1.add(shannonfanoButton);
		shannonfanoButton.setText("Shannon-fano");
		shannonfanoButton
				.addActionListener(new java.awt.event.ActionListener() {
					public void actionPerformed(java.awt.event.ActionEvent evt) {
						shannonfanoButtonActionPerformed(evt);
					}
				});

		buttonGroup1.add(lzwButton);
		lzwButton.setText("LZW");
		lzwButton.addActionListener(new java.awt.event.ActionListener() {
			public void actionPerformed(java.awt.event.ActionEvent evt) {
				lzwButtonActionPerformed(evt);
			}
		});

		jLabel1.setText("Select algorithm:");

		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
		this.setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addGap(21, 21, 21)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.LEADING)
												.addComponent(
														messageLabel,
														javax.swing.GroupLayout.Alignment.TRAILING,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														Short.MAX_VALUE)
												.addGroup(
														layout.createSequentialGroup()
																.addGroup(
																		layout.createParallelGroup(
																				javax.swing.GroupLayout.Alignment.LEADING)
																				.addComponent(
																						jLabel1)
																				.addComponent(
																						lzwButton)
																				.addComponent(
																						shannonfanoButton)
																				.addComponent(
																						rleButton)
																				.addGroup(
																						layout.createSequentialGroup()
																								.addComponent(
																										compressButton)
																								.addGap(32,
																										32,
																										32)
																								.addComponent(
																										decompressButton)))
																.addGap(0,
																		375,
																		Short.MAX_VALUE))
												.addGroup(
														layout.createSequentialGroup()
																.addGroup(
																		layout.createParallelGroup(
																				javax.swing.GroupLayout.Alignment.LEADING,
																				false)
																				.addComponent(
																						selectFolderButton,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						Short.MAX_VALUE)
																				.addComponent(
																						loadFileButton,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						Short.MAX_VALUE))
																.addGap(18, 18,
																		18)
																.addGroup(
																		layout.createParallelGroup(
																				javax.swing.GroupLayout.Alignment.LEADING)
																				.addComponent(
																						inputLabel,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						javax.swing.GroupLayout.DEFAULT_SIZE,
																						Short.MAX_VALUE)
																				.addComponent(
																						outputTextField))))
								.addContainerGap()));
		layout.setVerticalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addGap(27, 27, 27)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(loadFileButton)
												.addComponent(inputLabel))
								.addGap(18, 18, 18)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(
														outputTextField,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(
														selectFolderButton))
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED,
										48, Short.MAX_VALUE)
								.addComponent(jLabel1)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(rleButton)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(shannonfanoButton)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
								.addComponent(lzwButton)
								.addGap(18, 18, 18)
								.addComponent(messageLabel)
								.addGap(13, 13, 13)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(compressButton)
												.addComponent(decompressButton))
								.addContainerGap()));
	}// </editor-fold>//GEN-END:initComponents

	private void loadFileButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_loadFileButtonActionPerformed
		int returnVal = loadFileChooser.showOpenDialog(this);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			System.out.println("You chose to open this file: "
					+ loadFileChooser.getSelectedFile().getName());
			inputLabel.setText(loadFileChooser.getSelectedFile().getPath());
		}
		checkIfDataAvailable();
	}// GEN-LAST:event_loadFileButtonActionPerformed

	private void rleButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_rleButtonActionPerformed
		checkIfDataAvailable();
	}// GEN-LAST:event_rleButtonActionPerformed

	private void selectFolderButtonActionPerformed(
			java.awt.event.ActionEvent evt) {// GEN-FIRST:event_selectFolderButtonActionPerformed
		selectFolderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int returnVal = selectFolderChooser.showOpenDialog(this);
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			System.out.println("You chose to open this file: "
					+ selectFolderChooser.getSelectedFile().getName());
			if (selectFolderChooser.getSelectedFile().getPath().endsWith("\\")) {
				outputTextField.setText(selectFolderChooser.getSelectedFile()
						.getPath());
			} else {
				outputTextField.setText(selectFolderChooser.getSelectedFile()
						.getPath() + "\\");
			}
		}
		checkIfDataAvailable();
	}// GEN-LAST:event_selectFolderButtonActionPerformed

	private void outputTextFieldActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_outputTextFieldActionPerformed
		if (!outputTextField.getText().isEmpty()) {
			checkIfDataAvailable();
		}
	}// GEN-LAST:event_outputTextFieldActionPerformed

	private void compressButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_compressButtonActionPerformed
		try {
			switch (buttonGroup1.getSelection().getActionCommand()) {
			case "rle":
				compressionAlgorithm = new Rle();
				compressionAlgorithm.compress(
						new FileInputStream(inputLabel.getText()),
						new FileOutputStream(outputTextField.getText()));
				messageLabel.setText("Compression succeeded");
				calculateCompressionRate();
				break;
			case "sf":

				Encoder encode = new Encoder(inputLabel.getText(),
						outputTextField.getText());
				try {
					encode.encodeFile();
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this,e.toString());
				}
				calculateCompressionRate();

				break;
			case "lzw":
				compressionAlgorithm = new Lzw();
				compressionAlgorithm.compress(
						new FileInputStream(inputLabel.getText()),
						new FileOutputStream(outputTextField.getText()));
				messageLabel.setText("Compression succeeded");
				calculateCompressionRate();
				break;
			default:
			}
			inputFilePath = inputLabel.getText();
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
			messageLabel.setText("Compression failed.");
		}
	}// GEN-LAST:event_compressButtonActionPerformed

	private void decompressButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_decompressButtonActionPerformed
		try {
			switch (buttonGroup1.getSelection().getActionCommand()) {
			case "rle":
				compressionAlgorithm = new Rle();
				compressionAlgorithm.decompress(
						new FileInputStream(inputLabel.getText()),
						new FileOutputStream(outputTextField.getText()));
				messageLabel.setText("Decompression succeeded");
				// calculateCompressionRate();
				break;
			case "sf":

				Decoder decoder = new Decoder(inputLabel.getText(),
						outputTextField.getText());
				messageLabel.setText("Decompression succeeded");
				try {
					decoder.decodeFile();
				} catch (Exception e) {
					JOptionPane.showMessageDialog(this,e.toString());
				}

				break;
			case "lzw":
				compressionAlgorithm = new Lzw();
				compressionAlgorithm.decompress(
						new FileInputStream(inputLabel.getText()),
						new FileOutputStream(outputTextField.getText()));
				messageLabel.setText("Decompression succeeded");
				// calculateCompressionRate();
				break;
			default:
			}
			// calculatePSNR();
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
			messageLabel.setText("Decompression failed.");
		}
	}// GEN-LAST:event_decompressButtonActionPerformed

	private void shannonfanoButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_shannonfanoButtonActionPerformed
		checkIfDataAvailable();
	}// GEN-LAST:event_shannonfanoButtonActionPerformed

	private void lzwButtonActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_lzwButtonActionPerformed
		checkIfDataAvailable();
	}// GEN-LAST:event_lzwButtonActionPerformed

	private void calculatePSNR() {
		try {
			FileInputStream in = new FileInputStream(inputFilePath);
			FileInputStream out = new FileInputStream(outputTextField.getText());

			long size = 0;
			int a = 0;
			int b = 0;
			int maxa = 0;
			double mse = 0;
			while (((a = in.read()) != -1) && ((b = out.read()) != -1)) {
				size++;
				if (a > maxa) {
					maxa = a;
				}
				mse += Math.pow((a - b), 2);
			}
			System.out.println("MSE: " + mse);
			mse = mse / (double) size;
			System.out.println("MSE: " + mse);
			double psnr = 20 * Math.log10(((double) maxa / (double) Math
					.sqrt(mse)));
			System.out.println("PSNR: " + psnr);
		} catch (Exception e) {
			System.out.println("Error: " + e.getMessage());
		}
	}

	private void calculateCompressionRate() {
		File in = new File(inputLabel.getText());
		File out = new File(outputTextField.getText());
		// System.out.println("in: "+in.length()+" "+out.length());
		double compressionRate = (double) (in.length() - out.length())
				/ (double) in.length();
		System.out.println("Compression rate: " + compressionRate);
		// messageLabel.setText(messageLabel.getText()+" "+compressionRate);
	}

	private void checkIfDataAvailable() {
		if (!inputLabel.getText().isEmpty()
				&& !outputTextField.getText().isEmpty()
				&& !outputTextField.getText().endsWith("\\")
				&& buttonGroup1.getSelection() != null) {
			compressButton.setEnabled(true);
			decompressButton.setEnabled(true);
		} else {
			compressButton.setEnabled(false);
			decompressButton.setEnabled(false);
		}
	}

	// DocumentListener methods

	public void insertUpdate(DocumentEvent ev) {
		checkIfDataAvailable();
	}

	public void removeUpdate(DocumentEvent ev) {
		checkIfDataAvailable();
	}

	public void changedUpdate(DocumentEvent ev) {
	}

	// Variables declaration - do not modify//GEN-BEGIN:variables
	private javax.swing.ButtonGroup buttonGroup1;
	private javax.swing.JButton compressButton;
	private javax.swing.JButton decompressButton;
	private javax.swing.JLabel inputLabel;
	private javax.swing.JLabel jLabel1;
	private javax.swing.JButton loadFileButton;
	private javax.swing.JRadioButton lzwButton;
	private javax.swing.JLabel messageLabel;
	private javax.swing.JTextField outputTextField;
	private javax.swing.JRadioButton rleButton;
	private javax.swing.JButton selectFolderButton;
	private javax.swing.JRadioButton shannonfanoButton;
	// End of variables declaration//GEN-END:variables
}
